package com.yyy.service;

import com.yyy.repository.BaseRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;

/**
 * Created by admin on 2018/8/7.
 */

public abstract class AbstractBaseService<T, ID extends Serializable, Repository extends BaseRepository<T, ID>> {
    /**
     * 日志.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractBaseService.class);

    /**
     * 数据库实体基类.
     */
    @Autowired
    protected Repository repository;

    @Transactional
    public ServiceResult<T> save(final T entity){
        final T result = repository.save(entity);
        return new ServiceResult<>(result);
    }

    @Transactional
    public ServiceResult<List<T>> save(final List<T> entitys) {
        final List<T> results = repository.saveAll(entitys);
        return new ServiceResult<>(results);
    }

    @Transactional
    public ServiceResult delete(final ID id){
        try {
            repository.deleteById(id);
            return new ServiceResult();
        } catch (final IllegalArgumentException ae) {
            return new ServiceResult(Boolean.FALSE, "id不能为空");
        }catch (final EmptyResultDataAccessException re) {
            return new ServiceResult(Boolean.FALSE, "没有找到对应的实体,请刷新页面后重试");
        }
    }

    @Transactional
    public ServiceResult delete(final T entity) {
        try {
            repository.delete(entity);
            return new ServiceResult();
        } catch (final IllegalArgumentException e) {
            return new ServiceResult(Boolean.FALSE, "没有找到对应的实体");
        }

    }

    @Transactional
    public ServiceResult delete(final List<ID> ids) {
        final Iterator<ID> iterator = ids.iterator();
        while(iterator.hasNext()) {
            final ID id = iterator.next();
            try {
                repository.deleteById(id);
            } catch (final EmptyResultDataAccessException e) {
                LOGGER.error(e.getMessage(), e);
            }
        }
        return new ServiceResult();
    }

    @Transactional
    public ServiceResult deleteInBatch(final Iterable<T> entitys) {
        repository.deleteInBatch(entitys);
        return new ServiceResult();
    }

    @Transactional
    public ServiceResult deleteAllInBatch() {
        repository.deleteAllInBatch();
        return new ServiceResult();
    }

    public ServiceResult<T> findOne(final ID id){
        final T entity;
        try {
            entity = repository.getOne(id);
        } catch (final IllegalArgumentException e) {
            return new ServiceResult<>(Boolean.FALSE, "id不能为空");
        }
        if(entity == null) {
            return new ServiceResult<>(Boolean.FALSE, "没有找到对应的内容");
        }
        return new ServiceResult<>(entity);
    }

    public ServiceResult<List<T>> queryAll(){
        final List<T> retsults = repository.findAll();
        return new ServiceResult<>(retsults);
    }

    public Page<T> queryAll(final Pageable page){
        return repository.findAll(page);
    }

    public ServiceResult<List<T>> queryAll(final Specification spec, final Sort sort) {
        final List<T> results = repository.findAll(spec, sort);
        return new ServiceResult<>(results);
    }

    public Page<T> queryAll(final Specification spec, final Pageable page){
        return repository.findAll(spec, page);
    }

    public ServiceResult<List<T>> queryAll(final Sort sort){
        final List<T> results = repository.findAll(sort);
        return new ServiceResult<>(results);
    }

    public ServiceResult<List<T>> queryAll(final Specification spec) {
        final List<T> results = repository.findAll(spec);
        return new ServiceResult<>(results);
    }
}
